In a computing architecture utilizing stack-based memory allocation, stacks may reference regions within a memory where data is added/removed in a last-in-first-out (“LIFO”) method. The stack may be used to store local variables that are used within a thread or application. The stack may be used to keep track of a point to which each subroutine should return control when execution is terminated. Typically, a program is subdivided into reusable parts called subroutines, or functions, wherein these subroutines may be called in different parts of the same program. When executed, these subroutines often reserve a section of the stack for exclusive use, called the subroutine's stack frame. Therefore, after executing the subroutine, the program may refer to a return address of the subroutine within its stack frame, in order to remember where the execution should return.
Within a typical computer system, each execution thread may have a reserved region of memory referred to as the stack for that thread. While an application executes a function or procedure, the thread may add data to the top of its stack. The adding of data to a stack may be referred to as “winding”. Once the function or procedure has finished executing, the thread is responsible for removing that data from the stack. The removal of data from the stack may be referred to as “unwinding”. Accordingly, if a region of memory resides on the stack of a thread, that memory may be defined as being allocated on the stack.
Stack crawling may be used in a debugger and/or other software analysis programs in order to interpret an application at specific points of execution. Specifically, within the stack of the thread, a program may crawl the stack in an attempt to find the objects being used by the application. Stack crawling may allow for implementation of several important language features, such as, for example, garbage collection, security, exception processing, etc. Furthermore, stack crawling may also be used for profiling a dynamic call chain. According to conventional methods for crawling the stack, the runtime needs a mechanism that maps a call site's address to the descriptor containing the call site (i.e., “the caller”). Conventional techniques for stack unwinding require the compiler to register the address ranges comprising a method with the managed runtime. The managed runtime maintains a data structure that maps instruction ranges to method descriptors. Furthermore, it is important to note that conventional stack crawling methods require the application to be running while the programmer performs the stack crawl.